Logotipo do IFSC Logotipo do DACC Logotipo do Curso de Geoprocessamento Logotipo da disciplina PAG014903

Fundamentos de Programação em Python

v0.0.1

Padrão

Mapas Interativos com Python e Folium

Transforme dados geográficos em experiências interativas: domine o Folium, personalize visualizações e publique mapas navegáveis que contam histórias.

Você vai aprender a

  • Criar mapas interativos com poucos comandos em Python.
  • Personalizar zoom, marcadores, ícones e camadas de fundo.
  • Construir visualizações temáticas a partir de arquivos CSV.

1. Por que mapas interativos?

Depois de coletar, limpar e analisar dados geográficos, falta um passo decisivo: comunicar os resultados. Planilhas ou gráficos contam parte da história, mas é o mapa que permite enxergar padrões espaciais, comparar regiões e responder rapidamente às perguntas de quem toma decisão. Mapas interativos vão além da imagem estática porque oferecem zoom, filtros e popups que aproximam o público dos dados com poucos cliques.

O Folium é a ponte entre o Python — onde os dados já estão organizados — e o Leaflet, biblioteca JavaScript que o navegador entende. Em vez de escrever código web manualmente, descrevemos o mapa em Python, adicionamos camadas, marcadores ou estilos, e exportamos um único arquivo HTML que roda offline, pode ser enviado por e-mail ou incorporado em relatórios interativos.

Use Folium quando precisar:

  • Apresentar resultados de análises espaciais sem depender de softwares GIS proprietários.
  • Compartilhar mapas temáticos com equipes técnicas e público leigo mantendo interatividade.
  • Prototipar aplicações geográficas antes de investir em desenvolvimento web completo.
  • Integrar dados tabulares (CSV) com coordenadas gerando visualizações navegáveis em minutos.

Garanta que sua máquina tenha os pacotes necessários atualizados. No terminal do VS Code, execute:

Instalação rápida

python -m pip install folium

Verifique a versão disponível com python -m pip show folium.

2. Folium em ação

Blocos fundamentais do Folium

  • folium.Map: define centro, zoom, tiles e comportamento geral do mapa.
  • Elementos de overlay: marcadores, linhas, polígonos, GeoJSON ou choropleths que vão sobre o mapa base.
  • Camadas: TileLayer, FeatureGroup e LayerControl permitem alternar informações rapidamente.
  • Métodos de visualização: .show_in_browser() abre o mapa em um arquivo temporário; .save() gera uma versão definitiva; .get_root().render() retorna o HTML em string.

2.1 folium.Map

O objeto folium.Map concentra a configuração inicial: centro, zoom, tiles, escala e limites. A partir dele adicionamos marcadores e camadas.

import folium

# Centro aproximado do IFSC - Câmpus Florianópolis
centro = [-27.59397, -48.54235]

mapa = folium.Map(
    location=centro,
    zoom_start=14,
    tiles='OpenStreetMap',
    control_scale=True
)

folium.CircleMarker(
    location=centro,
    radius=8,
    color='#1B5E20',
    fill=True,
    fill_color='#2E7D32',
    popup='IFSC - Campus Florianópolis',
    tooltip='Passe o mouse para ver o nome'
).add_to(mapa)

mapa.show_in_browser()

O método show_in_browser() cria um arquivo temporário e abre o mapa no navegador padrão, ideal para verificações rápidas.

2.2 Camadas

Combine diferentes fontes de tiles e sobreposições temáticas para permitir que o usuário alterne a visualização rapidamente.

import folium

mapa = folium.Map(location=[-27.59, -48.54], zoom_start=13)

# Camadas de fundo
folium.TileLayer('OpenStreetMap', name='Ruas').add_to(mapa)
folium.TileLayer(
    tiles='https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}',
    attr='Esri',
    name='Satélite'
).add_to(mapa)
folium.TileLayer('Stamen Terrain', name='Relevo').add_to(mapa)

# Sobreposição opcional
folium.Circle(
    location=[-27.593, -48.558],
    radius=800,
    color='#1B5E20',
    fill=True,
    fill_opacity=0.1,
    tooltip='Raio de influência'
).add_to(mapa)

folium.LayerControl(collapsed=False).add_to(mapa)
mapa.show_in_browser()

Ative LayerControl para que a pessoa usuária escolha quais camadas visualizar e teste o resultado diretamente no navegador.

2.3 save() x show_in_browser()

  • mapa.save('arquivo.html'): gera um arquivo definitivo que pode ser versionado, publicado ou enviado para terceiros. Use quando precisar distribuir o mapa.
  • mapa.show_in_browser(): cria um arquivo temporário e abre automaticamente no navegador padrão. Ótimo para inspeções rápidas durante o desenvolvimento.
  • Ambos podem ser usados no mesmo script. Uma prática comum é testar com show_in_browser() e, satisfeito com o resultado, salvar a versão final com save().

3. Organização do projeto

Dica do professor

Monte uma estrutura previsível: /scripts para notebooks ou arquivos .py, /arquivos para CSV e shapefiles, e uma pasta /saidas para os HTML gerados. Caminhos relativos curtos evitam erros e facilitam publicar todo o pacote em repositórios ou ambientes educacionais.

4. Controlando zoom e layout

Ajustando a janela do mapa

O recorte inicial influencia a mensagem do mapa. Ajuste centro, zoom e limites para orientar o olhar de quem consulta a visualização.

  • zoom_start: aproximação inicial. Use 4–6 para visão regional, 12–14 para cidades, 17+ para quadras.
  • min_zoom e max_zoom: impedem que o usuário se afaste ou aproxime demais.
  • max_bounds: define recorte geográfico obrigatório, útil para delimitar municípios ou unidades de conservação.
  • width/height e control_scale: controlam dimensões e exibem barra de escala.
mapa_com_controles = folium.Map(
    location=[-27.6, -48.55],
    zoom_start=12,
    min_zoom=10,
    max_zoom=17,
    max_bounds=[[-27.75, -48.75], [-27.45, -48.35]],
    control_scale=True,
    tiles='CartoDB positron'
)

mapa_com_controles.show_in_browser()

Se o mapa ficar restrito demais, amplie os limites do max_bounds ou ajuste o zoom máximos. Teste em diferentes tamanhos de tela.

5. Trabalhando com marcadores

Marcadores, popups e tooltips

Marcadores são ideais para destacar pontos de interesse. Você pode construir o marcador em uma linha ou configurá-lo previamente para reutilizar em loops.

mapa = folium.Map(location=[-27.59397, -48.54235], zoom_start=13)

folium.Marker(
    location=[-27.59397, -48.54235],
    popup=folium.Popup('IFSC - Câmpus Florianópolis', max_width=250),
    tooltip='Clique ou toque para saber mais'
).add_to(mapa)

folium.Marker(
    location=[-27.5998, -48.5483],
    popup='Terminal Rita Maria',
    tooltip='Terminal rodoviário'
).add_to(mapa)

mapa.show_in_browser()

Ícones temáticos e agrupamento

Use ícones personalizados para reforçar categorias e agrupe grandes quantidades de pontos para melhorar o desempenho.

  • folium.Icon suporta as paletas padrão (verde, azul, vermelho…) e os símbolos da Font Awesome.
  • folium.DivIcon cria marcadores com HTML próprio (números, emojis, imagens).
  • folium.plugins.MarkerCluster reúne vários pontos em um cluster expansível.
from folium.plugins import MarkerCluster

mapa = folium.Map(location=[-27.59, -48.54], zoom_start=12)
cluster = MarkerCluster(name='Infraestrutura').add_to(mapa)

pontos = [
    {'nome': 'Biblioteca Central', 'coord': (-27.5946, -48.5452), 'icone': ('blue', 'book')},
    {'nome': 'Centro Integrado de Cultura', 'coord': (-27.5942, -48.5481), 'icone': ('green', 'film')},
    {'nome': 'Hospital Universitário', 'coord': (-27.5951, -48.5250), 'icone': ('red', 'plus-square')}
]

for ponto in pontos:
    cor, simbolo = ponto['icone']
    folium.Marker(
        location=ponto['coord'],
        popup=ponto['nome'],
        icon=folium.Icon(color=cor, icon=simbolo, prefix='fa')
    ).add_to(cluster)

mapa.show_in_browser()

6. Atenção às licenças

Crédito das camadas é obrigatório

Sempre informe a origem dos tiles (atributo attr) e respeite as condições de uso. Serviços como Esri, Mapbox ou Here costumam exigir chave de API, limite de requisições e crédito visível em tela.

Ao publicar mapas online, revise as políticas de cada provedor, evite armazenar chaves diretamente no código e, quando possível, utilize serviços de código aberto como OpenStreetMap ou tiles gerados pela própria instituição.

7. Alternando camadas base

Camadas base e sobreposições

Permita que a pessoa usuária alterne entre diferentes representações e ative informações auxiliares como limites ou pontos temáticos.

mapa = folium.Map(location=[-27.59, -48.54], zoom_start=13)

# Camadas de fundo (basemaps)
folium.TileLayer('OpenStreetMap', name='Ruas').add_to(mapa)
folium.TileLayer(
    tiles='https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}',
    attr='Esri',
    name='Satélite'
).add_to(mapa)
folium.TileLayer('Stamen Terrain', name='Relevo').add_to(mapa)

# Camada temática adicional usando GeoJSON
limite_ilha = folium.GeoJson(
    data='arquivos/limite_florianopolis.geojson',
    name='Limite municipal',
    style_function=lambda feat: {
        'color': '#1B5E20',
        'weight': 2,
        'fillOpacity': 0
    }
)
limite_ilha.add_to(mapa)

folium.LayerControl(collapsed=False).add_to(mapa)
mapa.show_in_browser()

O arquivo GeoJSON deve estar na mesma pasta ou acessível via caminho relativo. Ajuste collapsed para True se quiser um controle mais compacto.

8. Laboratório prático

Balneabilidade das praias

Vamos construir um mapa temático que colore cada praia conforme a situação de balneabilidade divulgada pelo órgão ambiental. Usaremos o CSV disponível em arquivos/Pontos.csv.

Passo 1 · Conferindo os dados

Antes de mapear, abra o CSV em um editor ou notebook e verifique se os campos Longitude e Latitude estão numéricos e com o separador decimal correto.

Praia,Latitude,Longitude,Situação
Praia da Barra,-27.600218,-48.573928,Boa
Praia Mole,-27.605612,-48.448782,Regular
Praia dos Ingleses,-27.432509,-48.399489,Ruim
Praia do Campeche,-27.658957,-48.489882,Boa
Praia do Santinho,-27.409855,-48.368907,Ruim
Praia da Joaquina,-27.637142,-48.436796,Regular
Praia de Canasvieiras,-27.432064,-48.500224,Boa
Praia do Pântano do Sul,-27.739187,-48.502771,Regular

Passo 2 · Script em Python

Use Pandas para ler o arquivo, calcule a média das coordenadas para centralizar o mapa e mapeie as categorias para cores e ícones.

import folium
import pandas as pd

df = pd.read_csv('arquivos/Pontos.csv')
centro = [df['Latitude'].mean(), df['Longitude'].mean()]

cores = {
    'Boa': ('green', 'smile-o'),
    'Regular': ('orange', 'meh-o'),
    'Ruim': ('red', 'frown-o')
}

mapa = folium.Map(location=centro, zoom_start=12)

for _, linha in df.iterrows():
    situacao = linha['Situação']
    cor, icone = cores.get(situacao, ('gray', 'question'))
    folium.Marker(
        location=[linha['Latitude'], linha['Longitude']],
        popup=f"{linha['Praia']} — Situação: {situacao}",
        tooltip=linha['Praia'],
        icon=folium.Icon(color=cor, icon=icone, prefix='fa')
    ).add_to(mapa)

folium.LayerControl().add_to(mapa)
mapa.show_in_browser()
print('Mapa das praias aberto no navegador padrão.')

Ajuste as palavras das categorias para corresponder exatamente ao CSV. Se novas classificações surgirem, atualize o dicionário cores.

9. Criando Mapas Coropléticos (Choropleth Maps)

Mapas coropléticos (do grego khōros, "área", e plēthos, "multidão") colorizam regiões conforme uma variável estatística. São ideais para visualizar como indicadores como população, renda ou densidade se distribuem no território.

O Folium simplifica esse processo com folium.Choropleth. Você precisa de duas peças principais:

  • Dados geográficos: um arquivo GeoJSON com as geometrias das áreas (por exemplo, municípios).
  • Dados estatísticos: um DataFrame do Pandas com a chave de cada área e o valor que será mapeado.

Exemplo prático · PIB per capita de Santa Catarina

Vamos unir a malha municipal do IBGE com um conjunto de dados fictícios de PIB per capita para criar um mapa temático.

import folium
import geopandas as gpd
import pandas as pd

# 1. Carregar a malha municipal
url_geojson = "https://raw.githubusercontent.com/tbrugz/geodata-br/master/geojson/geo1-mun-42-sc.json"
gdf_sc = gpd.read_file(url_geojson)
gdf_sc['CD_MUN'] = gdf_sc['CD_MUN'].astype(str)  # garante chave em string

# 2. Criar um DataFrame com os dados estatísticos
dados_pib = {
    'codigo_municipio': ['4205407', '4202404', '4208203', '4204202', '4209102'],
    'pib_per_capita': [60000, 85000, 55000, 95000, 72000]
}
df_pib = pd.DataFrame(dados_pib)
df_pib['codigo_municipio'] = df_pib['codigo_municipio'].astype(str)

# 3. Criar o mapa base
mapa_sc = folium.Map(location=[-27.5, -50.5], zoom_start=7, tiles='CartoDB positron')

# 4. Adicionar a camada coroplética
folium.Choropleth(
    geo_data=gdf_sc,
    name='PIB per capita (SC)',
    data=df_pib,
    columns=['codigo_municipio', 'pib_per_capita'],
    key_on='feature.properties.CD_MUN',
    fill_color='YlGnBu',
    fill_opacity=0.7,
    line_opacity=0.2,
    legend_name='PIB per Capita (R$)',
    highlight=True
).add_to(mapa_sc)

folium.LayerControl().add_to(mapa_sc)

# 5. Salvar o mapa
mapa_sc.save('mapa_pib_sc.html')

Substitua a lista dados_pib por um CSV real e garanta que a coluna de código use o mesmo formato do GeoJSON (geralmente 7 dígitos para municípios).

Entendendo os parâmetros-chave

  • geo_data: GeoDataFrame ou caminho para o GeoJSON contendo as geometrias.
  • data: DataFrame com a métrica a ser mapeada.
  • columns: lista com a coluna-chave e a coluna de valores.
  • key_on: caminho até a chave dentro do GeoJSON (ex.: feature.properties.CD_MUN).

Inspecione seu GeoJSON para confirmar o nome exato da propriedade e ajuste fill_color para combinar com a paleta desejada.

10. Explorando plugins e extras

Próximos passos com plugins

Amplie a experiência com extensões já incluídas no Folium.

Marcadores arrastáveis

import folium
from folium.plugins import DragMarker

mapa = folium.Map(location=[-27.59, -48.54], zoom_start=14)

DragMarker(
    [-27.59397, -48.54235],
    popup='Arraste-me para a posição correta!'
).add_to(mapa)

mapa.show_in_browser()

Popups ricos

import folium

html_popup = """
    

Ponte Hercílio Luz

Ponte Hercílio Luz

A ponte é um cartão-postal de Florianópolis.

Saiba mais """ iframe = folium.IFrame(html_popup, width=280, height=280) popup = folium.Popup(iframe, max_width=280) mapa = folium.Map(location=[-27.5930, -48.5615], zoom_start=16) folium.Marker( location=[-27.5930, -48.5615], popup=popup, tooltip='Clique para ver!' ).add_to(mapa) mapa.show_in_browser()

Mapas de calor

import folium
from folium.plugins import HeatMap
import random

mapa = folium.Map(location=[-27.59, -48.54], zoom_start=12)

pontos = [
    [-27.59 + (random.random() - 0.5) * 0.1,
     -48.54 + (random.random() - 0.5) * 0.2]
    for _ in range(100)
]

HeatMap(pontos).add_to(mapa)
mapa.show_in_browser()

10. Curiosidade

Curiosidade: integração com Jupyter

O Folium renderiza mapas diretamente em notebooks Jupyter ou Google Colab. Use mapa como última instrução da célula ou display(mapa) para visualizar sem salvar arquivos. Isso acelera protótipos e relatórios exploratórios.

11. Exercícios rápidos

1. Ajuste de zoom personalizado

Usando o mapa básico, aplique min_zoom e max_zoom para limitar a navegação a uma região de interesse.

2. Marcadores em lote

Crie uma lista de coordenadas e, com um for, adicione marcadores coloridos automaticamente. Use um dicionário para mapear categorias a ícones.

3. Popup multimídia

Monte um popup com HTML, incluindo uma imagem e um link. Salve o resultado como mapa_popup_personalizado.html.

12. Conclusão

Fechamento

Você aprendeu a transformar dados tabulares e geoespaciais em mapas navegáveis, com controle total sobre zoom, camadas e marcadores. Dominar Folium significa comunicar resultados sem depender de softwares pesados ou longas instruções para o público final.

Continue combinando Folium com bibliotecas como GeoPandas e Shapely para análises espaciais mais complexas — os mapas interativos serão a vitrine ideal para seus insights.